package com.xinqi.modules.chat.favorite.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xinqi.common.base.error.CommonErrors;
import com.xinqi.common.core.enums.FavoriteLimitEnum;
import com.xinqi.common.core.utils.MessageUtils;
import com.xinqi.common.core.utils.StringUtils;
import com.xinqi.common.mybatis.data.service.impl.BaseServiceImpl;
import com.xinqi.modules.chat.favorite.convert.FavoriteTagConvert;
import com.xinqi.modules.chat.favorite.domain.FavoriteTagEntity;
import com.xinqi.modules.chat.favorite.dto.req.FavoriteTagCreateDTO;
import com.xinqi.modules.chat.favorite.dto.req.FavoriteTagDeleteDTO;
import com.xinqi.modules.chat.favorite.dto.req.FavoriteTagUpdateDTO;
import com.xinqi.modules.chat.favorite.dto.rsp.FavoriteTagResultDTO;
import com.xinqi.modules.chat.favorite.mapper.FavoriteTagMapper;
import com.xinqi.modules.chat.favorite.service.FavoriteTagService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 收藏标签表服务层实现
 *
 * @author: yyzhen
 * @date: 2023/03/23
 */
@Service("favoriteTagService")
@RequiredArgsConstructor
public class FavoriteTagServiceImpl extends BaseServiceImpl<FavoriteTagMapper, FavoriteTagEntity> implements FavoriteTagService {
    private final FavoriteTagConvert favoriteTagConvert;

    /**
     * 查询用户标签列表
     *
     * @Title:
     * @MethodName: listByUserId
     * [keywords, userId]
     * @Return java.util.List<com.xinqi.modules.chat.favorite.dto.rsp.FavoriteTagResultDTO>
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/4/17 10:11
     */
    @Override
    public List<FavoriteTagResultDTO> listByUserId(String keywords, Long userId) {
        LambdaQueryWrapper<FavoriteTagEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FavoriteTagEntity::getUserId, userId)
            .like(StringUtils.isNotEmpty(keywords), FavoriteTagEntity::getTitle, keywords)
            .orderByDesc(FavoriteTagEntity::getCreateTime);
        return this.baseMapper.selectDtoList(wrapper, favoriteTagConvert::convert);
    }

    /**
     * 查询标签详情
     *
     * @Title:
     * @MethodName: findById
     * [id]
     * @Return com.xinqi.modules.chat.favorite.dto.rsp.FavoriteTagResultDTO
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/3/23 14:04
     */
    @Override
    public FavoriteTagResultDTO findById(Long id) {
        CommonErrors.BAD_REQUEST.check(Objects.nonNull(id), MessageUtils.message("chat.favorite.tag.id.not.blank"));
        return this.baseMapper.selectDtoById(id, favoriteTagConvert::convert);
    }

    /**
     * 添加收藏标签
     *
     * @Title:
     * @MethodName: insert
     * [dto]
     * @Return java.lang.Boolean
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/3/23 13:59
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insert(FavoriteTagCreateDTO dto) {

        //校验标签名重复
        FavoriteTagEntity check = selectByTitleAndUserId(dto.getTitle(), dto.getOperationUserId());
        CommonErrors.BAD_REQUEST.check(Objects.isNull(check), MessageUtils.message("chat.favorite.tag.is.exists"));

        //校验标签名是否超过最大值
        LambdaQueryWrapper<FavoriteTagEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FavoriteTagEntity::getUserId, dto.getOperationUserId());
        Long count = this.baseMapper.selectCount(wrapper);
        CommonErrors.BAD_REQUEST.check(count < FavoriteLimitEnum.MAX_LENGTH.getNumber(), MessageUtils.message("chat.favorite.tag.max.valid"));

        // 新增标签
        FavoriteTagEntity entity = new FavoriteTagEntity();
        entity.setTitle(dto.getTitle());
        entity.setUserId(dto.getOperationUserId());

        return this.save(entity);
    }

    /**
     * 修改收藏标签
     *
     * @Title:
     * @MethodName: updateById
     * [dto]
     * @Return java.lang.Boolean
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/3/23 13:59
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateById(FavoriteTagUpdateDTO dto) {

        //校验标签名重复
        FavoriteTagEntity check = selectByTitleAndUserId(dto.getTitle(), dto.getOperationUserId());
        if (Objects.nonNull(check)) {
            CommonErrors.BAD_REQUEST.check(Objects.equals(check.getId(), dto.getId()), MessageUtils.message("chat.favorite.tag.is.exists"));
        }

        // 校验标签是否存在
        FavoriteTagEntity old = Optional.ofNullable(this.getById(dto.getId()))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException(MessageUtils.message("data.does.not.exist")));
        CommonErrors.BAD_REQUEST.check(Objects.equals(dto.getOperationUserId(), old.getUserId()), MessageUtils.message("chat.favorite.tag.update.fail"));

        // 修改标签名称
        FavoriteTagEntity entity = new FavoriteTagEntity();
        entity.setTitle(dto.getTitle());
        entity.setUserId(dto.getOperationUserId());
        entity.setId(dto.getId());
        return this.updateById(entity);
    }


    /**
     * 删除收藏标签
     *
     * @Title:
     * @MethodName: deleteById
     * [dto]
     * @Return java.lang.Boolean
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/3/23 13:59
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(FavoriteTagDeleteDTO dto) {
        FavoriteTagEntity old = Optional.ofNullable(this.getById(dto.getId()))
            .orElseThrow(() -> CommonErrors.BAD_REQUEST.asException(MessageUtils.message("data.does.not.exist")));
        CommonErrors.BAD_REQUEST.check(Objects.equals(dto.getOperationUserId(), old.getUserId()), MessageUtils.message("chat.favorite.tag.remove.fail"));

        return this.deleteById(dto.getId());
    }

    /**
     * 根据标签名和用户查询标签
     *
     * @Title:
     * @MethodName: selectByTitleAndUserId
     * [title, userId]
     * @Return com.xinqi.modules.chat.favorite.domain.FavoriteTagEntity
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/3/23 17:23
     */
    @Override
    public FavoriteTagEntity selectByTitleAndUserId(String title, Long userId) {
        LambdaQueryWrapper<FavoriteTagEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FavoriteTagEntity::getUserId, userId)
            .eq(FavoriteTagEntity::getTitle, title)
            .last("LIMIT 1");
        return this.baseMapper.selectOne(wrapper);
    }

    /**
     * 收藏，输入标签名（校验标签，有则返回标签ID，没有保存标签并返回标签ID）
     *
     * @Title:
     * @MethodName: checkByTitleAndUserId
     * [title, userId]
     * @Return java.lang.Long
     * @Exception
     * @Description:
     * @author: yyzhen
     * @date: 2023/3/23 17:33
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long checkByTitleAndUserId(String title, Long userId) {
        FavoriteTagEntity entity = checkFavoriteTag(title, userId);
        return entity.getId();
    }

    /**
     * 根据标签名集合获取标签ID集合
     *
     * @param titles
     * @param userId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Long> checkByTitlesAndUserId(List<String> titles, Long userId) {
        List<Long> tagIds = new ArrayList<>();
        for (String title : titles) {
            FavoriteTagEntity entity = checkFavoriteTag(title, userId);
            tagIds.add(entity.getId());
        }
        return tagIds;
    }

    // 校验标签是否存在不存在新增
    private FavoriteTagEntity checkFavoriteTag(String title, Long userId) {
        FavoriteTagEntity check = selectByTitleAndUserId(title, userId);
        if (Objects.isNull(check)) {

            //校验标签名是否超过最大值
            LambdaQueryWrapper<FavoriteTagEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FavoriteTagEntity::getUserId, userId);
            Long count = this.baseMapper.selectCount(wrapper);
            CommonErrors.BAD_REQUEST.check(count < FavoriteLimitEnum.MAX_LENGTH.getNumber(), MessageUtils.message("chat.favorite.tag.max.valid"));

            // 添加新标签
            FavoriteTagEntity entity = new FavoriteTagEntity();
            entity.setTitle(title);
            entity.setUserId(userId);
            this.save(entity);
            return entity;
        } else {
            return check;
        }
    }

}
